<?php
namespace addons\command\controller;

use app\admin\controller\Addon;
use app\admin\facade\ThinkAddons;
use think\facade\Cache;
use think\facade\Db;

/**
 * Class Development
 * @package app\admin\controller\Addon
 * @ControllerAnnotation(title="一键curd")
 */
class Development extends Addon
{
    /**
     * @NodeAnotation(title="添加")
     */
    public function add()
    {
        $s_time = time();
        $result = '';
        $cmd    = '';
        if ($this->request->isAjax()) {
            $post = $this->request->request();
            $post = array_filter($post);
            $type = $post['type'];
            switch ($type) {
                case 'crud':
                    $cmd = $this->createCmd($post);
                    if (@$post['cmd'] == 1) {
                        return json($cmd);
                    } else {
                        if (env('mango.is_demo')) {
                            $result = '演示环境禁止执行';
                        } else {
                            
                            shell_exec($cmd);
                            $result = Cache::get('phpthink');
                        }
                    }
                    break;
                case 'menu':
                    $cmd = $this->createMenu($post);
                    Cache::clear();
                    if ($post['cmd'] == 1) {
                        return json($cmd);
                    } else {
                        $result = 'success';
                        // dd($result);
                    }
                    break;
                case 'interface':
                    $this->createFunction($post);
                    break;
                // 插件
                case 'addons':
                    $this->createAddons($post);
                    break;
                default:
                    # code...
                    break;
            }
            $rule                = [];
            $post['content']     = $result;
            $post['command']     = $cmd;
            $post['createtime']  = time();
            $post['executetime'] = time() - $s_time;
            $post['status']      = $result ? 'successed' : 'failured';
            $post['params']      = str_replace('php think curd -t ', '', $cmd);
            $post['params']      = str_replace('php think menu ', '', $post['params']);
            $this->validate($post, $rule);
            try {
                $save = $this->model->save($post);
            } catch (\Exception $e) {
                $this->error('保存失败:' . $e->getMessage());
            }
            $save ? $this->success('保存成功', $result) : $this->error('保存失败');
        }
        // 数据库所有表
        $tables = Db::getTables();
        $this->assign('tables', $tables);
        // 控制器
        $adminPath   = ROOT_PATH . 'app/admin/controller/';
        $controllers = $this->get_controller_list($adminPath);
        $this->assign('controllers', $controllers);
        $adminPath      = ROOT_PATH . 'app/api/controller/';
        $apicontrollers = $this->get_controller_list($adminPath);
        $this->assign('apicontrollers', $apicontrollers);
        // api模型
        $adminPath = ROOT_PATH . 'app/api/model/';
        $apimodels = $this->get_controller_list($adminPath);
        $this->assign('apimodels', $apimodels);
        // 插件
        $addons = ThinkAddons::getLocalAddonsName();
        $this->assign('addons', $addons);
        return $this->fetch();
    }

    /**
     * 创建插件
     */
    private function createAddons($post)
    {
        $set_addons = $post['set_addons'];
        switch ($set_addons) {
            case '1':
                // 新建插件
                $name = $post['addons_name'];
                if (is_dir(app()->getRootPath() . 'addons' . DIRECTORY_SEPARATOR . $name)) {
                    $this->error('插件' . $name . '存在');
                } else {
                    copydirs('../extend/mango/demo', '../addons/' . $name);
                    //判断拷贝成功
                    if (!is_dir(app()->getRootPath() . 'addons' . DIRECTORY_SEPARATOR . $name)) {
                        $this->error('拷贝插件失败，请重试');
                    } else {
                        $this->handelNewAddons($post, $name);
                        $this->success('新增插件成功');
                    }
                }
                break;
            case '2':
                $maddons = $post['maddons'];
                $caddons = $post['caddons'];
                if (file_exists('../addons/' . $maddons . '/controller/' . ucfirst($caddons) . '.php')) {
                    $this->error('子插件' . $caddons . '存在');
                }
                copy('../extend/mango/demo/controller/Demo.php', '../addons/' . $maddons . '/controller/' . ucfirst($caddons) . '.php');
                // 添加插件
                $this->handelAddAddons($post, $maddons, $caddons);
                break;
            default:
                // code...
                break;
        }
        $this->success('生成插件成功');
    }

    /**
     * [handelAddAddons description]
     * @Author   sky
     * @DateTime 2021-10-13T11:23:24+0800
     * @param    [type]                   $post [description]
     * @param    [type]                   $name [description]
     * @return   [type]                         [description]
     */
    public function handelAddAddons($post, $maddons, $caddons)
    {
        $dir = app()->getRootPath() . 'addons' . DIRECTORY_SEPARATOR . $maddons . '/';
        // 替换控制器
        file_put_contents($dir . 'controller/' . ucfirst($caddons) . '.php', str_replace('{__DEMO__}', $caddons, file_get_contents($dir . 'controller/' . ucfirst($caddons) . '.php')));
    }

    /**
     * [handelNewAddons description]
     * @Author   sky
     * @DateTime 2021-10-12T11:35:17+0800
     * @param    [type]                   $post [description]
     * @param    [type]                   $name [description]
     * @return   [type]                         [description]
     */
    private function handelNewAddons($post, $name)
    {
        $dir = app()->getRootPath() . 'addons' . DIRECTORY_SEPARATOR . $name . '/';
        // 替换主插件
        file_put_contents($dir . 'Plugin.php', str_replace('{__DEMO__}', $name, file_get_contents($dir . 'Plugin.php')));
        // 替换info
        file_put_contents($dir . 'info.ini', str_replace('{__DEMO__}', $name, file_get_contents($dir . 'info.ini')));
        // 替换控制器
        file_put_contents($dir . 'controller/Demo.php', str_replace('{__DEMO__}', $name, file_get_contents($dir . 'controller/Demo.php')));
        rename($dir . 'controller/Demo.php', $dir . 'controller/' . ucfirst($name) . '.php');
        // 替换模型
        file_put_contents($dir . 'model/Demo.php', str_replace('{__DEMO__}', $name, file_get_contents($dir . 'model/Demo.php')));
        rename($dir . 'model/Demo.php', $dir . 'model/' . ucfirst($name) . '.php');
        // 替换视图
        rename($dir . 'view/demo', $dir . 'view/' . ($name));
        // 替换js
        file_put_contents($dir . 'js/demo.js', str_replace('{__DEMO__}', $name, file_get_contents($dir . 'js/demo.js')));
        rename($dir . 'js/demo.js', $dir . 'js/' . ($name) . '.js');

        return true;
    }

    /**
     * 根据表名称获取字段
     */
    public function getFields()
    {
        $tableName = $this->request->get('table_name', 'm_mall_cate');
        $fields    = Db::getFields($tableName);
        $keys      = array_keys($fields);
        foreach ($keys as $key => &$value) {
            $res['name']  = $value;
            $res['value'] = $value;
            $result[]     = $res;
        }
        return json($result);
    }

    /**
     * 创建phpcmd命令
     */
    private function createCmd($post)
    {
        // 表前缀
        $prefix = config('database.connections.mysql.prefix');
        // 主表
        $mtable = $post['mtable'];
        $mtable = str_replace($prefix, '', $mtable);
        // 主表
        $main_cmd = $this->mainTable($post);
        // 基础命令
        $cmd = 'php think curd -t ' . $mtable;
        // 有主表
        if ($main_cmd) {
            $cmd .= $main_cmd;
        }
        // 模型设置
        $set_model = @$post['set_model'];
        // 模型设置
        $cmd_model = $this->setModel($set_model, $post);

        return $cmd . $cmd_model;
    }

    /**
     * 模型设置
     */
    private function setModel($set_model, $post)
    {
        // 命令
        $cmd = '';
        // 存在模型设置
        if ($set_model) {
            // 关联模型
            $relation = @$set_model['relation'];
            if ($relation) {
                $cmd .= $this->relationModel($post);
            }
            // 全局模型
            $global = @$set_model['global'];
            if ($global) {
                $cmd .= $this->globalModel();
            }
            // 删除模型
            $delete = @$set_model['delete'];
            if ($delete) {
                $cmd .= $this->deleteModel();
            }
            // 强制覆盖模型
            $force = @$set_model['force'];
            if ($force) {
                $cmd .= $this->forceModel();
            }
        }

        return $cmd;
    }

    /**
     * 关联模型
     */
    private function relationModel($post)
    {
        $prefix = config('database.connections.mysql.prefix');
        $cmd    = '';
        // 关联数量
        $numbers = $post['numbers'];
        // 循环数量
        for ($i = 1; $i <= $numbers; $i++) {
            $otable = str_replace($prefix, '', $post['otable' . $i]);
            // -r test_cate --foreignKey=cate_id --primaryKey=id
            $cmd .= ' -r ' . $otable . ' --foreignKey=' . $post['okey' . $i] . ' --primaryKey=' . $post['mkey' . $i] . ' --relationOnlyFileds=' . $post['ofields' . $i] . ' --relationBindSelect=name';
        }

        return $cmd;
    }

    /**
     * 全局模型
     */
    private function globalModel()
    {

    }

    /**
     * 删除模型
     */
    private function deleteModel()
    {
        return ' -d 1';
    }

    /**
     * 强制覆盖模型
     */
    private function forceModel()
    {
        return ' -f 1';
    }

    /**
     * 主表
     */
    private function mainTable($post)
    {
        $cmd = '';
        // 主表字段
        $mfields = $post['mfields'];
        if ($mfields) {
            $mfields_arr = explode(',', $mfields);
            foreach ($mfields_arr as $key => $value) {
                $cmd .= ' --ignoreFields=' . $value . ' ';
            }
        }
        // 主表控制器
        $controller = @$post['controller'];
        if ($controller) {
            $cmd .= ' -c ' . $controller;
        }
        // 主表模型
        $model = @$post['model'];
        if ($model) {
            $cmd .= ' -m ' . $model;
        }
        return $cmd;
    }

    /**
     * 获取控制器列表
     * @internal
     */
    public function get_controller_list($adminPath)
    {
        $adminPath     = str_replace('\public\..', '', $adminPath);
        $controllerDir = $adminPath;
        // dd($controllerDir);
        $files = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
        );
        $list = [];
        foreach ($files as $name => $file) {
            if (!$file->isDir()) {
                $filePath = $file->getRealPath();
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
                    $controllerDir = str_replace('/', '\\', $controllerDir);
                }
                $name   = str_replace($controllerDir, '', $filePath);
                $name   = str_replace(DS, "/", $name);
                $list[] = ['id' => $name, 'name' => $name];
            }
        }
        return $list;
        $pageNumber = $this->request->request("pageNumber");
        $pageSize   = $this->request->request("pageSize");
        return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]);
    }

    /**
     * 创建菜单
     */
    private function createMenu($post)
    {
        $mtable    = $post['mtable'];
        $mtable    = str_replace('/', '.', $mtable);
        $mtable    = str_replace('.php', '/index', $mtable);
        $mtable    = strtolower($mtable);
        $set_model = @$post['set_model'];
        if ($set_model) {
            $delete = @$set_model['delete'];
            if ($delete) {
                $del_menu = Db::name('system_menu')->where('href', $mtable)->delete();
                if ($del_menu) {
                    $this->error('', '删除成功！');
                }
            }
        }

        $menu_data = [
            'pid'         => 2,
            'title'       => $post['name_menu'],
            'icon'        => $post['icon'],
            'href'        => $mtable,
            'target'      => '_self',
            'create_time' => time(),
        ];
        if (env('mango.is_demo')) {
            $this->error('', '演示环境禁止执行！');
        }
        if ($post['cmd'] == 1) {
            goto b;
        }
        if (@$set_model['force']) {
            Db::name('system_menu')->where('href', $mtable)->delete();
            Db::name('system_menu')->insert($menu_data);
        } else {
            $menu = Db::name('system_menu')->where('href', $mtable)->find();
            if (!$menu) {
                Db::name('system_menu')->insert($menu_data);
            } else {
                $this->error('', '菜单已经存在！');
            }
        }
        b:
        return 'php think menu --controller ' . $post['mtable'];
    }

    /**
     * 创建模型
     */
    public function createModel()
    {
        $params = $this->request->request();
        if (!$params['model']) {
            $this->error('数据表不存在！');
        }
        // 替换表前缀
        $prefix     = config('database.connections.mysql.prefix');
        $model_name = str_replace($prefix, '', $params['model']);
        $model_name = ucfirst(
            preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $model_name)
        );
        // 生成模型
        $model_file = file_get_contents('../addons/command/lib/tpl/model.tpl');
        if (!$model_file) {
            $this->error('模型模板不存在！');
        }

        $model_path = '../app/api/model/' . $model_name . '.php';
        // 判断模型是否存在
        if (file_exists($model_path)) {
            $this->error('模型存在！');
        }

        $file   = str_replace('{$modelName}', $model_name, $model_file);
        $result = file_put_contents($model_path, $file);

        if ($result) {
            $this->success('生成模型' . $model_name . '成功！');
        }

        $this->error('生成失败！');
    }

    /**
     * 生成控制器文件
     */
    public function createInterface()
    {
        $params = $this->request->request();
        if (!$params['controller']) {
            $this->error('请输入控制器名称！');
        }
        $controller_name = ucfirst(str_replace(' ', '', $params['controller'])) . '.php';
        // 生成控制器
        $controller_file = file_get_contents('../addons/command/lib/tpl/controller.tpl');
        if (!$controller_file) {
            $this->error('控制器模板不存在！');
        }

        $controller_path = '../app/api/controller/' . $controller_name;
        // 判断控制器是否存在
        if (file_exists($controller_path)) {
            $this->error('控制器存在！');
        }
        $controller_desc = $params['desc'] ? $params['desc'] : $controller_name;
        $controller_file = str_replace('@Apidoc\Title("controller")', '@Apidoc\Title("' . $controller_desc . '")', $controller_file);
        $file            = str_replace('{$controllerName}', str_replace('.php', '', $controller_name), $controller_file);

        $result = file_put_contents($controller_path, $file);
        if ($result) {
            $this->success('生成控制器' . $controller_name . '成功！');
        }
        $this->error('生成失败！');
    }

    /**
     * 创建具体接口
     */
    private function createFunction($post)
    {
        // 判断类型
        $set_interface = @$post['set_interface'];

        switch ($set_interface) {
            case 'add':
                $this->addCreateFunction($post, $set_interface);
                break;
            case 'edit':
                $this->addCreateFunction($post, $set_interface);
                break;
            case 'del':
                $this->addCreateFunction($post, $set_interface);
                break;
            case 'list':
                $this->addCreateFunction($post, $set_interface);
                break;
            default:
                $this->error('请选择生成的接口类型！');
                break;
        }
        //
    }

    /**
     * 添加接口
     */
    private function addCreateFunction($post, $edit = 0)
    {
        $interface_name = $post['interface_name'];
        if (!$interface_name) {
            $this->error('请上传接口名称');
        }
        $param_name = @$post['param_name'];
        if (!$param_name) {
            $this->error('请上传参数');
        }
        $params                                   = [];
        list($data, $rule, $message, $param_data) = [[], [], [], []];
        foreach ($param_name as $key => $value) {
            if ($value) {
                // 验证
                if (@$post['param_validation'][$key]) {
                    $data[$value]    = "input('$value')";
                    $rule[$value]    = "require";
                    $message[$value] = $post['param_desc'][$key] . "不能为空";
                }
                //组装数据
                if (@$post['param_data'][$key]) {
                    $param_data[$value] = "input('$value')";
                }
                // 组装新数组
                array_push($params, $value . ',' . @$post['param_desc'][$key] . ',' . @$post['param_validation'][$key]);
            }
        }
        // 生成验证器
        if ($data && $rule && $message) {
            $validate = $this->createValidate($data, $rule, $message);
        } else {
            $validate = '';
        }
        $mtable     = $post['mtable'];
        $model_path = '../app/api/model/' . $mtable;
        // 判断模型是否存在
        if (!file_exists($model_path)) {
            $this->error($mtable . '模型不存在！');
        }
        // 组装数据
        $handel_data = $this->handelData($param_data);
        $model_name  = '\app\api\model\\' . str_replace('.php', '', $mtable);
        // 新增或者编辑
        switch ($edit) {
            case 'add':
                $model_path = $this->createAdd($model_name);
                break;
            case 'edit':
                $model_path = $this->createEdit($model_name, $post);
                break;
            case 'del':
                $model_path = $this->createDel($model_name, $post);
                break;
            case 'list':
                $model_path = $this->createList($model_name, $post);
                break;
            default:
                $this->error('请选择添加的接口类型！');
                break;
        }
        $func = "$validate
            $handel_data
            $model_path
        \$this->success('ok',\$res);";
        // 取出接口模板
        $function_file = file_get_contents('../addons/command/lib/tpl/function.tpl');
        if (!$function_file) {
            $this->error('控接口模板不存在！');
        }
        $function_file = str_replace('{function}', $interface_name, $function_file);
        $function_file = str_replace('{__CONTENT__}', $func, $function_file);
        //是否开启接口文档
        if (@$post['set_model']['doc'] == 'on') {
            $function_file = str_replace('* NotParse', '', $function_file);
        }
        $mcontroller = $post['mcontroller'];
        // 处理接口文档
        $function_file = $this->handelApiDoc($function_file, $model_name, $mcontroller, $interface_name, $post, $param_name, $edit);

        $controller_path = '../app/api/controller/' . $mcontroller;
        // 判断控制器是否存在
        if (file_exists($controller_path)) {
            // 强制替换模式
            if (@$post['set_model']['force'] == 'on') {
                $this->interfateForce($controller_path, $interface_name);
            }

            $controller = file_get_contents($controller_path);
            // 判断方法是否存在
            $obj = '\app\api\controller\\' . str_replace('.php', '', $mcontroller);
            if (method_exists($obj, $interface_name)) {
                $this->error('接口已经存在！');
            }
            // 替换最后一个}
            $point      = strrpos($controller, '}');
            $controller = (substr_replace($controller, '', $point));
            file_put_contents($controller_path, $controller);
        } else {
            $this->error('接口文件不存在！');
        }
        // dd($function_file);
        file_put_contents($controller_path, $function_file, FILE_APPEND);
        file_put_contents($controller_path, PHP_EOL, FILE_APPEND);
        $result = file_put_contents($controller_path, '}', FILE_APPEND);
        if ($result) {
            $this->success('生成接口' . $interface_name . '成功！');
        }
        $this->error('生成失败！');
    }

    /**
     * @DateTime 2021-08-14T16:20:30+0800
     * @param    [type]                   $model_name [description]
     */
    private function createAdd($model_name)
    {
        $model_path = '$res = ' . $model_name . '::insert($result);';
        $str        = "
        try {
            $model_path
        }catch (\Exception \$e){
            \$this->error(\$e->getMessage());
        }
        ";
        return $str;
    }

    /**
     * 添加验证
     */
    private function createValidate($data, $rule, $message)
    {
        // list($data, $rule, $message) = [json_encode($data), json_encode($rule), json_encode($message)];
        $data    = $this->arr2str($data, $t = 1);
        $rule    = $this->arr2str($rule, $t = 1);
        $message = $this->arr2str($message, $t = 1);
        $res     = "\$result = \$this->validate(
            [
                $data
            ],
            [
                $rule
            ],
            [
                $message
            ]
        );
        if (true !== \$result) {
            // 验证失败 输出错误信息
            \$this->error(\$result);
        }";
        // dd($res);
        return $res;
    }

    /**
     * 数组转字符串
     */
    private function arr2str($arr, $t = 0)
    {
        // dump($arr);
        $str = null;
        $pad = str_pad("", $t, "\t");
        $i   = 0;
        foreach ($arr as $k => $v) {
            if (is_array($v)) {
                if (is_string($k)) {
                    $str .= $pad . "'" . $k . "'=>array(\n" . arr2str($v, $t + 1) . $pad . "),\n";
                } else {
                    $str .= $pad . "array(\n" . arr2str($v, $t + 1) . $pad . "),\n";
                }
            } else {
                if (is_string($k)) {
                    // dump($pad);
                    // dd($i);
                    //去除input的引号
                    if (strstr($v, 'input(') != false) {
                        $v = "'=>" . $v;
                    } else {
                        $v = "'=>'" . $v . "'";
                    }
                    if ($i == 0) {
                        $str .= "'" . $k . $v . ",\n\t\t\t";
                    } else if ($i + 1 == count($arr)) {
                        $str .= $pad . "'" . $k . $v . ",\t";
                    } else {
                        $str .= $pad . "'" . $k . $v . ",\n\t";
                    }
                } else {
                    $str .= $pad . "'" . $v . "',\n\t\t\t";
                }
            }
            $i++;
        }
        return $str;
    }

    /**
     * 处理数据
     */
    private function handelData($data)
    {
        $data = $this->arr2str($data, $t = 1);
        $res  = <<<EOF
            \n\t\t\$result =
        [
            $data
        ];
EOF;
        return $res;
    }

    /**
     * @Author   sky
     * @DateTime 2021-06-11T14:22:06+0800
     * @param    [type] controller_path
     * @param    [type] interface_name
     * @return   [type] ''
     */
    private function interfateForce($controller_path, $interface_name)
    {
        $a     = file_get_contents($controller_path);
        $need  = 'function ' . $interface_name . '()';
        $aa    = strpos($a, $need);
        $start = $aa;
        $aa -= 7;
        $aaa  = strrpos($a, $need);
        $aaa  = $aaa - $aa + strlen($need);
        $file = substr_replace($a, '', $aa, $aaa);
        // dd($start, $file);
        if ($start) {
            file_put_contents($controller_path, $file);
        }
    }

    //===============================编辑接口==============================

    private function createWhere($where)
    {
        $new_where = [];
        foreach ($where as $key => $value) {
            $new_where[$value] = "input('$value')";
        }
        $data = $this->arr2str($new_where, $t = 0);

        $data_str = "[$data]";
        $data_str = str_replace(array("\r\n", "\t", "\n"), "", $data_str);
        // dd($data_str);
        return $data_str;
    }

    /**
     * @param $model_name
     * @param $post
     * @return string
     */
    private function createEdit($model_name, $post)
    {
        // 编辑
        $where   = @$post['interface_where'];
        $whereOr = @$post['interface_whereOr'];
        if (!$where || !$whereOr) {
            $this->error('where条件不能为空！');
        }
        if ($where && !$whereOr) {
            $where      = explode(',', $where);
            $where_data = $this->createWhere($where);
            $model_path = '$res = ' . $model_name . '::where(' . $where_data . ')->update($result);';
        }
        if ($whereOr && !$where) {
            $whereOr      = explode(',', $whereOr);
            $whereOr_data = $this->createWhere($whereOr);
            $model_path   = '$res = ' . $model_name . '::whereOr(' . $whereOr_data . ')->update($result);';
        }
        if ($whereOr && $where) {
            $whereOr      = explode(',', $whereOr);
            $where        = explode(',', $where);
            $whereOr_data = $this->createWhere($whereOr);
            $where_data   = $this->createWhere($where);
            // dd($where_data);
            $model_path = '$res = ' . $model_name . '::where(' . $where_data . ')->whereOr(' . $whereOr_data . ')->update($result);';
        }
        $str = "
        try {
            $model_path
        }catch (\Exception \$e){
            \$this->error(\$e->getMessage());
        }
        ";
        return $str;
    }

    /**
     * @param $model_name
     * @param $post
     * @return string
     */
    private function createDel($model_name, $post)
    {
        // 编辑
        $where   = @$post['interface_where'];
        $whereOr = @$post['interface_whereOr'];
        if ($where && !$whereOr) {
            $where      = explode(',', $where);
            $where_data = $this->createWhere($where);
            $model_path = '$res = ' . $model_name . '::where(' . $where_data . ')->delete();';
        }
        if ($whereOr && !$where) {
            $whereOr      = explode(',', $whereOr);
            $whereOr_data = $this->createWhere($whereOr);
            $model_path   = '$res = ' . $model_name . '::whereOr(' . $whereOr_data . ')->delete();';
        }
        if ($whereOr && $where) {
            $whereOr      = explode(',', $whereOr);
            $where        = explode(',', $where);
            $whereOr_data = $this->createWhere($whereOr);
            $where_data   = $this->createWhere($where);
            // dd($where_data);
            $model_path = '$res = ' . $model_name . '::where(' . $where_data . ')->whereOr(' . $whereOr_data . ')->delete();';
        }
        $str = "
        try {
            $model_path
        }catch (\Exception \$e){
            \$this->error(\$e->getMessage());
        }
        ";
        return $str;
    }

    //=================================处理接口文档===============================

    /**
     * @param $function_file
     * @param $model_name
     * @param $mcontroller
     * @param $interface_name
     * @param $post
     * @return array|string|string[]
     */
    private function handelApiDoc($function_file, $model_name, $mcontroller, $interface_name, $post, $param_name, $edit)
    {
        // 处理标题
        $function_file = str_replace('Title("title")', 'Title("' . $post['interface_title'] . '")', $function_file);
        // 处理描述
        $function_file = str_replace('Desc("desc")', 'Desc("' . $post['interface_desc'] . '")', $function_file);
        // 处理地址
        $function_file = str_replace('Url("url")', 'Url("' . '/api/' . str_replace('.php', '', $mcontroller) . '/' . $interface_name . '")', $function_file);
        // 接口模式
        switch ($edit) {
            case 'add':
            case 'edit':
            case 'del':
                // 处理文档模型
                $function_file = str_replace('@Apidoc\Returned("data",type="array",ref="model")', '', $function_file);
                // 处理分页
                $function_file = str_replace('@Apidoc\Returned(ref="pagingParam")', '', $function_file);
                $function_file = str_replace('@Apidoc\Param(ref="pagingParam")', '', $function_file);
                // 处理返回值
                $function_file = str_replace('@Apidoc\Returned("returned",type="string",desc="returned")', '', $function_file);
                break;
            case 'list':
                $find_interface = $post['find_interface'];
                // 处理文档模型
                $function_file = str_replace('ref="model"', 'ref="' . $model_name . '\getFieldsDesc"', $function_file);
                // 处理返回值
                $function_file = str_replace('@Apidoc\Returned("returned",type="string",desc="returned")', '', $function_file);
                if ($find_interface == 'find') {
                    $function_file = str_replace('@Apidoc\Returned(ref="pagingParam")', '', $function_file);
                    $function_file = str_replace('@Apidoc\Param(ref="pagingParam")', '', $function_file);
                }
                break;
            default:
                // 处理文档模型
                $function_file = str_replace('ref="model"', 'ref="' . $model_name . '\getFieldsDesc"', $function_file);
                // 处理分页
                $function_file = str_replace('@Apidoc\Returned(ref="pagingParam")', '', $function_file);
                $function_file = str_replace('@Apidoc\Param(ref="pagingParam")', '', $function_file);
                // 处理返回值
                $function_file = str_replace('@Apidoc\Returned("returned",type="string",desc="returned")', '', $function_file);
                break;
        }
        // 处理参数
        if ($param_name) {
            $params = '';
            // * @Apidoc\Param("param",type="string",require=true,desc="param")
            // $post['param_desc'][$key]
            foreach ($param_name as $key => $value) {
                if ($value) {
                    $param_validation = $post['param_validation'][$key];
                    $param_desc       = $post['param_validation'][$key];

                    $params .= <<<EOH
* @Apidoc\Param("$value",type="string",require="$param_validation",desc="$param_desc")
EOH;
                }
            }
            $function_file = str_replace('* @Apidoc\Param("param",type="string",require=true,desc="param")', $params, $function_file);
        }
        return $function_file;
    }

    //==========================================处理查询=================================
    /**
     * @param $model_name
     * @param $post
     * @return string
     */
    private function createList($model_name, $post)
    {
        // 编辑
        $where   = @$post['interface_where'];
        $whereOr = @$post['interface_whereOr'];
        $with    = $this->relationInterfaceModel($post);
        $with    = trim($with);
        if (!$where) {
            $this->error('请填写where条件！');
        }
        if (!$post['find_interface']) {
            $this->error('请填写查询类型！');
        }
        if ($where && !$whereOr) {
            $where      = explode(',', $where);
            $where_data = $this->createWhere($where);
            $model_path = '$res = ' . $model_name . '::' . $with . 'where(' . $where_data . ')->' . $post['find_interface'] . '();';
        }
        if ($whereOr && !$where) {
            $whereOr      = explode(',', $whereOr);
            $whereOr_data = $this->createWhere($whereOr);
            $model_path   = '$res = ' . $model_name . '::' . $with . 'whereOr(' . $whereOr_data . ')->' . $post['find_interface'] . '();';
        }
        if ($whereOr && $where) {
            $whereOr      = explode(',', $whereOr);
            $where        = explode(',', $where);
            $whereOr_data = $this->createWhere($whereOr);
            $where_data   = $this->createWhere($where);
            // dd($where_data);
            $model_path = '$res = ' . $model_name . '::' . $with . 'where(' . $where_data . ')->whereOr(' . $whereOr_data . ')->' . $post['find_interface'] . '();';
        }
        $str = "
        try {
            $model_path
        }catch (\Exception \$e){
            \$this->error(\$e->getMessage());
        }
        ";
        return $str;
    }

    /**
     * 关联模型
     * @param $post
     * @return string
     */
    private function relationInterfaceModel($post)
    {
        $with   = '';
        $prefix = config('database.connections.mysql.prefix');
        $cmd    = '';
        // 关联数量
        $inumbers = @$post['inumbers'];
        // 循环数量
        for ($i = 1; $i <= $inumbers; $i++) {
            // 替换表前缀
            $otable = str_replace($prefix, '', $post['otable' . $i]);
            $otable = ucfirst(
                preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                    return strtoupper($match[1]);
                }, $otable)
            );
//            dd($otable);
            // 模型是否存在
            $this->hasModel($otable);
            // 写入模型关联
            $this->writeModel($otable, $post['otype' . $i], $post['okey' . $i], $post['mkey' . $i]);
            // 生成with
            $with = $this->withModel($otable, $post['otype' . $i], $post['okey' . $i], $post['mkey' . $i], $post['ofields' . $i]);
        }

        return $with;

    }

    /**
     * @param $otable
     */
    private function hasModel($otable)
    {
        echo $otable;
        $model_path = '../app/api/model/' . $otable . '.php';
        // 判断模型是否存在
        if (!file_exists($model_path)) {
            $this->error($otable . '模型不存在！');
        }
    }

    /**
     * @param $otable
     * @param $otype
     * @param $okey
     * @param $mkey
     */
    private function writeModel($otable, $otype, $okey, $mkey)
    {
        // 取出魔板
        $relation_file = file_get_contents('../addons/command/lib/tpl/relation.tpl');
        if (!$relation_file) {
            $this->error('关联模板不存在！');
        }
        // 替换关联模板
        $relation_file = str_replace('{model_name}', $otable, $relation_file);
        $relation_file = str_replace('{model_type}', $otype, $relation_file);
        $relation_file = str_replace('{okey}', $okey, $relation_file);
        $relation_file = str_replace('{mkey}', $mkey, $relation_file);
        $model_path    = '../app/api/model/' . $otable . '.php';
        $model_data    = file_get_contents($model_path);
        // 写入
        $relation_file = str_replace('// {__CONTENT__}', $relation_file, $model_data);
        return file_put_contents($model_path, $relation_file);
    }

    /**
     * @param $otable
     * @param $otype
     * @param $okey
     * @param $mkey
     * @param $ofields
     */
    private function withModel($otable, $otype, $okey, $mkey, $ofields)
    {
        $with = '';
        $with .= <<<EOH
                with(['$otable' => function(\$query) {
                    \$query->field('$ofields');
                }])->
EOH;
        return $with;
    }
}
